# 在测试视频(OpenCV安装目录\sources\samples\data)上，使用基于混合高斯模型的背景提取算法，提取前景并显示(显示二值化图像，前景为白色)
import cv2
# 加载视频
cap = cv2.VideoCapture()
cap.open('/Users/taotao/Desktop/vtest.avi')
if not cap.isOpened():#检查是否成功初始化
    print("无法打开视频文件")
pBgModel = cv2.createBackgroundSubtractorMOG2()#构造高斯混合模型

def labelTargets(img, mask, threshold):
    seg = mask.copy()
    cnts = cv2.findContours(seg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)#找出图片的轮廓，对其进行循环
    count = 0
    for i in cnts[1]:
        area = cv2.contourArea(i)
        if area < threshold:
            continue
        count += 1
        rect = cv2.boundingRect(i)#对于周长大于188的轮廓，计算外接矩阵
        print("矩形：X:{} Y:{} 宽：{} 高：{}".format(rect[0], rect[1], rect[2], rect[3]))
        cv2.drawContours(img, [i], -1, (255, 255, 0), 1)
        cv2.rectangle(img, (rect[0], rect[1]), (rect[0] + rect[2], rect[1] + rect[3]), (0, 0, 255), 1)#画出外接矩阵，作为人
        cv2.putText(img, str(count), (rect[0], rect[1]), cv2.FONT_HERSHEY_PLAIN, 0.5, (0, 255, 0))
    return count

while True:
    flag, source = cap.read()# 从视频中读取文件
    if not flag:
        break
    image = cv2.pyrDown(source)

    fgMask = pBgModel.apply(image)#使用上混合高斯模型

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))#定义矩形
    morphImage_open = cv2.morphologyEx(fgMask, cv2.MORPH_OPEN, kernel, iterations=5)#使用开运算进行噪音的去除
    mask = fgMask - morphImage_open
    _, Mask = cv2.threshold(mask, 30, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    # Mask = cv2.GaussianBlur(Mask, (5, 5), 0)
    targets = labelTargets(image, Mask, 30)

    print("共检测%s个目标" % targets)
    backGround = pBgModel.getBackgroundImage()
    foreGround = image - backGround
    cv2.imshow('source', image)#展示图片，
    cv2.imshow('background', backGround)
    cv2.imshow('foreground', Mask)
    key = cv2.waitKey(10)#延长放映时间，设置太低视频播放的很快，设置太高视频播放的很慢，通常25ms就可以
    if key == 27:#esc的意思
        break
